// 泛型 指在定义函数 接口或者类的时候不提前指定具体的数据类型 当使用时再指定具体的数据类型

// 函数使用泛型参数
// 提前设计数据类型 直接规定了数据类型
function fff(x:string,y:string):string{
    return x+y
}

// 数组的数据类型规定
// ['ss','ss']  string[]
// [11,22,33] number[]

// 没有规定数据类型
function fun<T>(x:T,y:T):T[]{
    return [x,y]
}
// 当调用时 传入数据类型
fun<string>('122','dhs');
console.log(fun<string>('122','dhs'));

fun<number>(12,23);
console.log(fun<number>(12,23));

// 返回值为元组tuple
function fofu<T,K>(a:T,b:K):[T,K]{
    return [a,b]
}
fofu<string,number>('hh',11);
fofu<string,boolean>('xx',false);

// 接口定义泛型
// function Person(){
//     name:String;
//     age:Number;
//     sex:String
// }
// let obj={
//     name:'tom',
//     age:11,
//     sex:'男'
// }
// console.log(obj);

// 将接口定义为一个泛型的接口
interface Person<T,K>{
    name:T,
    age:K,
    sex:T
}

let obj:Person<string,number>={
    name:'tom',
    age:12,
    sex:'男'
}
console.log(obj);

let obj1:Person<boolean,number>={
    name:false,
    age:10,
    sex:true
}
console.log(obj1); 

// 泛型类
// 一说到类或者构造函数  脑海必须想到三个地方： 自身的方法属性  实例对象上的方法和属性  原型对象上的方法和属性
// class Animal{
//     name:string;
//     age:number;
//     constructor(name:string,age:number){
//         this.name=name;
//         this.age=age;
//     }
//     // 原型对象上的方法
//     jump(str:string):string{
//         return this.name+str
//     }
//     // 静态方法
//     static run(num:number):number{
//         return num
//     }
// }

// 泛型类
class Animal<T,N>{
    name:T;
    age:N;
    constructor(name:T,age:N){
        this.name=name;
        this.age=age;
    }
    // 因为定义的泛型  如果做加法或者拼串
    jump(str:T):T{
        return str
    }
    // 静态成员不能引用类 类型形参
    // 静态成员 构造函数自身上的属性和方法
}
let dahuang = new Animal<string,number>('dahuang',2);
console.log(dahuang);
let xiaoming = new Animal<boolean,'xx'>(false,'xx');
console.log(xiaoming);

// 类的数据类型使用接口进行定义 泛型接口
interface Bass<T,K>{
    data:T[],
    add:(x:T,y:K)=>void
}

class User implements Bass<string,number>{
    // 在每一个实例对象行都添加了一个data值
    data:string[]=[];
    add(x:string,y:number):void{
        this.data.push(x);
        // 因为我们规定的data是字符串类型的数组 而是数字
        // this.data.push(y);
        console.log(y);
    }
}
let xiaohua = new User();
console.log(xiaohua);


// 泛型约束
// function boo<T>(x:T){
        // 因为T是类型传参 T传入的是什么值一定吗?
//     console.log(x.length); //报错
// }

// function boo1(x:string){
//     console.log(x.length)
// }
// function boo2(x:number){
//     console.log(x.length)
// }

interface Length{
    length:number
}
function boo3<T extends Length>(x:T){
    console.log(x.length)
}
// boo3('sss');
boo3<string>('shjdsh');

// ts基本数据类型  never
interface Test{
    name:string
}
// never用不存在的

function fooFun():never{
    while(true){}
}













export {
    fff
}